package com.cgycms.weblogserver.websocket;

import com.alibaba.fastjson.JSON;
import com.cgycms.weblogcommon.model.WebLogMeta;
import com.cgycms.weblogserver.model.JsonResult;
import com.cgycms.weblogserver.model.SessionConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @ClassName : WebSocketServer
 * @Description : 前后端交互，发送日志信息
 * @Author : cgy
 * @Date: 2020-09-14 17:47
 */
@ServerEndpoint(value = "/ws")
@Component
public class WebSocketServer {


    private static int onlineCount = 0;

    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

    private static Map<String, SessionConfig> sessionConfigMap = new ConcurrentHashMap<>();

    private Session session;

    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

    private static Set<String> menuSet = new TreeSet<>(new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareTo(o2);
        }
    });


    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);
        sessionConfigMap.put(session.getId(), new SessionConfig(null, true, true, true));
        sendMenuMessage();
        addOnlineCount();
        log.debug("有新连接加入！当前在线人数为{}", getOnlineCount());
    }

    @OnClose
    public void onClose(Session session) {
        webSocketSet.remove(this);
        subOnlineCount();
        log.debug("有一连接关闭！当前在线人数为{}", getOnlineCount());
        sessionConfigMap.remove(session.getId());
    }

    /**
     * 修改自定义配置
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        SessionConfig sessionConfig = JSON.parseObject(message, SessionConfig.class);
        sessionConfigMap.put(session.getId(), sessionConfig);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户:{},发生错误！e:{}", session.getId(), error);
        error.printStackTrace();
    }


    /**
     * 群发
     *
     * @param webLogMeta
     */
    public static void sendInfo(WebLogMeta webLogMeta) {
        for (WebSocketServer item : webSocketSet) {
            item.sendLogMessage(webLogMeta);
        }
    }

    /**
     * 发送日志
     *
     * @param webLogMeta
     */
    public void sendLogMessage(WebLogMeta webLogMeta) {

        //更新菜单
        if (!menuSet.contains(webLogMeta.getSource())) {
            menuSet.add(webLogMeta.getSource());
            sendMenuMessage();
        }

        SessionConfig sessionConfig = sessionConfigMap.get(this.session.getId());
        //加载对应菜单数据
        if (!StringUtils.isEmpty(sessionConfig.getSource())) {
            if (!sessionConfig.getSource().contains(webLogMeta.getSource())) {
                return;
            }
        }

        //日志头动态设置
        StringBuffer msg = new StringBuffer();
        msg.append("[" + webLogMeta.getSource() + "]");

        if (sessionConfig.isShowFileName()) {
            msg.append("[" + webLogMeta.getFileName() + "]");
        }

        if (sessionConfig.isShowIp()) {
            msg.append("[" + webLogMeta.getIp() + "]");
        }

        msg.append("-");
        msg.append(webLogMeta.getContent());
        this.session.getAsyncRemote()
                .sendText(JSON.toJSONString(JsonResult.resultSuccess(msg, "logData")));
    }


    /**
     * 发送菜单
     */
    public void sendMenuMessage() {
        this.session.getAsyncRemote().sendText(JSON.toJSONString(JsonResult.resultSuccess(this.menuSet, "menu")));
    }


    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }


}

